﻿using System;
using System.Collections.Generic;
using System.Data.Linq;
using System.Diagnostics.Contracts;
using System.Linq;
using IMModel.Domain.Common;

namespace IMModel.Domain
{
    /// <summary>
    /// Период
    /// </summary>
    partial class Term : ICacheble, IRespondentIndexVector, IItem
    {
        #region IRespondentIndexVector Members

        #region Indexes
        /// <summary>
        /// Получает итоговый индекс респондента
        /// </summary>
        /// <param name="respondent">Респондент</param>
        /// <returns>Индекс</returns>
        public double this[Respondent respondent]
        {
            get
            {
                Contract.Requires(Indexes != null);
                Contract.Requires(respondent != null);
                Contract.Requires(respondent.IsParticipant);
                Contract.Ensures(Contract.Result<double>() > 0);
                return Indexes[respondent];
            }
        }

        /// <summary>
        /// Получает итоговые индексы респондентов
        /// </summary>
        public RespondentIndexCollection Indexes
        {
            get
            {
                return CalcIndexes(IndexContext.Current);
                //return _respondentIndexCache;
            }
        }

        //private void CalcIndexes()
        //{
        //    Contract.Requires(TopmostParticipateSectionTerms != null);
        //    Contract.Ensures(Contract.ForAll(_respondentIndexCache, x => x.Key.Term == this));
        //    Contract.Ensures(Contract.ForAll(_respondentIndexCache, x => x.Key.IsParticipant));

        //    if (_respondentIndexCache != null) return;
        //    _respondentIndexCache = TopmostParticipateSectionTerms.GetIndexes(x => x.Weight / TotalWeight);
        //}
        #endregion

        #region CalcIndexes()
        private Dictionary<IndexContext, RespondentIndexCollection> _respondentIndexCaches;

        /// <summary>
        /// выборка по Section и расчёт индексов в соответствие с выбранной политикой
        /// </summary>
        public RespondentIndexCollection CalcIndexes(IndexContext сontext)
        {
            return CCache.Get(ref _respondentIndexCaches, сontext, () =>
                TopmostParticipateSectionTerms.Where(x => сontext.IndexObjectFilter(x.Section))
                .GetIndexes(сontext, x => x.Weight / TotalWeight));
        }
        #endregion

        #endregion

        #region ICacheble Members

        /// <summary>
        /// Сбрасывает кэшированное состояние объекта
        /// </summary>
        public void Invalidate()
        {
            Contract.Ensures(_totalWeight == null);
            //Contract.Ensures(_respondentIndexCache == null);
            Contract.Ensures(_indexRequiredCount == null);
            Contract.Ensures(_respondentCache == null);
            Contract.Ensures(_a == null);
            Contract.Ensures(_maxHarmony == null);
            Contract.Ensures(_respondentIndexCaches == null);

            _respondentIndexCaches = null;
            _a = null;
            _totalWeight = null;
            //_respondentIndexCache = null;
            _indexRequiredCount = null;
            _respondentCache = null;
            _maxHarmony = null;

            TopmostParticipateSectionTerms.Invalidate();
        }

        #endregion

        public string Years()
        {
            return  string.Format("{0}/{1}", Start.Year, Stop.Year);
        }
    }
}